package cn.net.vote.util;

import java.util.Date;
import java.util.UUID;

import cn.net.vote.data.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;

import cn.net.vote.data.domain.ReasonBean;
import cn.net.vote.data.domain.ResponseBodyBean;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.IncorrectClaimException;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.MissingClaimException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;

public class JwtUtil {
	/** 【描 述】：私钥 */
	private static final String SECRET = ConfigUtil.getString("jwtSecret");

	/** 
	 * 【描 述】：创建JWT
	 * @param issuer 该JWT的签发者
	 * @param ttlMillis 签名到期时间
	 * @return
	 */
	public static String createJWT(String issuer, User user, long ttlMillis) {

		long nowMillis = System.currentTimeMillis();
		Date now = new Date(nowMillis);

		// 设置JWT声明
		JwtBuilder builder = Jwts.builder()
				.setId(UUID.randomUUID().toString())// JWT ID
				.setHeaderParam("typ", "JWT")// 头信息
				.setIssuedAt(now)// 签证时间时间
				.setSubject(user.getId() + "")// 该JWT所面向的用户
				.setIssuer(issuer)// 该JWT的签发者
				.claim("username", user.getUsername())//用户名
				.claim("roleid", user.getRoleid())//权限id
				.claim("id", user.getId())//用户id
				.claim("idcard", user.getIdcard())//身份证号
				.claim("name", user.getName())//姓名
				.signWith(SignatureAlgorithm.HS256, SECRET.getBytes());//使用JWT签名算法，对token进行签名

		// 如果过期时间被指定，则添加到到期时间中
		if (ttlMillis >= 0) {
			long expMillis = nowMillis + ttlMillis;
			Date exp = new Date(expMillis);
			builder.setExpiration(exp);// 签名到期时间
		}

		// 将JWT序列换为一个紧凑、安全的URL字符串
		return builder.compact();
	}
	
	/** 
	 * 【描 述】：验证JWT
	 * @param compactJws
	 * @return
	 */
	public static ResponseBodyBean verifyJWT(String compactJws) {
		ResponseBodyBean apiBean = new ResponseBodyBean();
		ReasonBean reason = new ReasonBean();
		try {
			Jws<Claims> claims = Jwts.parser()
//					        .requireSubject("admin")
//					        .require("hasMotorcycle", true)
			        .setSigningKey(SECRET.getBytes())
			        .parseClaimsJws(compactJws);
			apiBean.setResult(claims.getBody().getSubject());
			reason.setCode("200");
			reason.setText("Token验证通过");
		} catch (ExpiredJwtException e) {
			System.err.println("JWT签名已经过期：" + e.getMessage());
			reason.setCode("500");
			reason.setText("JWT签名已经过期");
		} catch (SignatureException e) {
			System.err.println("claimJws JWS签名验证失败：" + e.getMessage());
			reason.setCode("500");
			reason.setText("JWS签名验证失败");
		} catch (MalformedJwtException e) {
			System.err.println("claimJws字符串不是有效的JWS：" + e.getMessage());
			reason.setCode("500");
			reason.setText("Token字符串不是有效的JWS");
		} catch(IllegalArgumentException e) {
			System.err.println("claimJws的字符串为空或为空，或仅为空格：" + e.getMessage());
			reason.setCode("500");
			reason.setText("Token字符串为空或仅为空格");
		} catch (UnsupportedJwtException e) {
			System.err.println("claimJws参数不代表Claim JWS：" + e.getMessage());
			reason.setCode("500");
			reason.setText("Jws参数不代表Claim JWS");
		} catch(MissingClaimException e) {
			System.err.println("1111"+e.getMessage());
			reason.setCode("500");
		} catch(IncorrectClaimException e) {
			System.err.println("22222"+ e.getMessage());
			reason.setCode("500");
		}
//		if(apiBean.getCode() != 1) {
//			apiBean.setNote("非法请求");
//		}
		apiBean.setReason(reason);
		return apiBean;
	}
	
	/** 
	 * 【描 述】：刷新Token
	 * @param token
	 * @return
	 */
	public static ResponseBodyBean refreshToken(String token) {
		ResponseBodyBean apiBean = verifyJWT(token);
		if(apiBean.getReason().getCode() == "200") {
			Claims claims = Jwts.parser().setSigningKey(SECRET.getBytes()).parseClaimsJws(token).getBody();
			User user = new User();
			user.setId(Integer.valueOf(claims.getSubject()));
			user.setUsername(claims.get("username") + "");
			user.setRoleid(Integer.parseInt(claims.get("roleid").toString()));
			user.setName(claims.get("name") + "");
			user.setIdcard(claims.get("idcard") + "");
			String jwtToken = createJWT("Secure Center", user, 30*60*1000);
			apiBean.setResult(jwtToken);
			return apiBean;
		}
		return apiBean;
	}
	
	/** 
	 * 【描 述】：解析Token
	 * @param compactJws
	 * @return
	 */
	public static Jws<Claims> parseJwt(String compactJws) {
		Jws<Claims> claims = Jwts.parser()
	        .setSigningKey(SECRET.getBytes())
	        .parseClaimsJws(compactJws);
		return claims;
	}
	
	public static void main(String[] args) {
		User user = new User();
		user.setId(1);
		user.setUsername("admin");
		user.setName("超级管理员");
		user.setIdcard("admin");
		user.setRoleid(1);
		JwtUtil jwtUtil = new JwtUtil();
		String creatToken = jwtUtil.creatToken(user);
		System.out.println(creatToken);
        refreshToken(creatToken);


	}
	
	public String creatToken(User user){
		Integer id = user.getId();
		String token = createJWT("Security Center", user, 24*24*60*60*1000);
		return token;
	}
	
}
